/* 
 * Copyright (c) 2019, CENTRIN.CIYUN.LTD. All rights reserved.
 */
package com.cory.boot.component.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

/**
 * netty配置类
 * @author xiongcong
 * @date 2019-07-24
 */
@Data
@Component
@ConfigurationProperties(prefix = "netty")
@ConditionalOnProperty(prefix = "netty", value = "port")
public class NettyConfig {
    
    private int port;

    private int bossThread = 1;

    private int workerThread = 1;

    private boolean keepalive = true;

    private int backlog = 100;
    
    private boolean ssl = false;
    private String sslPath;
    private String sslPwd;
    
    @Bean(name = "bossGroup", destroyMethod = "shutdownGracefully")
    public NioEventLoopGroup bossGroup(){
        return new NioEventLoopGroup(bossThread);
    }

    @Bean(name = "workerGroup", destroyMethod = "shutdownGracefully")
    public NioEventLoopGroup workerGroup(){
        return new NioEventLoopGroup(workerThread);
    }

    @Bean(name = "tcpSocketAddress")
    public InetSocketAddress tcpPost(){
        return new InetSocketAddress(port);
    }

    @Bean(name = "tcpChannelOptions")
    public Map<ChannelOption<?>, Object> tcpChannelOptions(){
        Map<ChannelOption<?>, Object> options = new HashMap<ChannelOption<?>, Object>();
        options.put(ChannelOption.SO_KEEPALIVE, keepalive);
        options.put(ChannelOption.SO_BACKLOG, backlog);
        return options;
    }

    @Autowired
    private NettyChannelInitializer initializer;

    @Bean(name = "serverBootstrap")
    @SuppressWarnings({"rawtypes", "unchecked"})
    public ServerBootstrap bootstrap() {
        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup(), workerGroup())
                .channel(NioServerSocketChannel.class)
                .handler(new LoggingHandler(LogLevel.DEBUG))
                .childHandler(initializer);
        Map<ChannelOption<?>, Object> tcpChannelOptions = tcpChannelOptions();
        Set<ChannelOption<?>> keySet = tcpChannelOptions.keySet();
        for (ChannelOption option : keySet) {
            b.option(option, tcpChannelOptions.get(option));
        }
        return b;
    }
}
